Mix c & ASM

簡介

為了加快效能與特殊需求可以使用,組合語言與c語言混和撰寫方式

os:linux(x64)(#e)

編譯器:gcc

接下來皆以64位元linux示範

與32位元會有所不一樣

Linux system call

第二手資源

System call implement location

linux原始碼

以下舉例:__x64_sys_write

  • syscall_64.tbl尋找__x64_sys_write

    根據該檔案知道 __x64_sys_write 編號1 所以暫存器%rax 填入1

  • 搜尋實做的函數

    1
    SYSCALL_DEFINEx(function_name,....){...}
    

    function_name:write

    x:這個編號不一定

__x64_sys_write

__x64_sys_write實做位置
我們看到ksys_write(fd, buf, count)有三個變數
根據ABI規則依序填入暫存器
fd %rdi
buf %rsi
count %rdx

1
2
3
4
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,size_t, count)
{
    return ksys_write(fd, buf, count);
}

根據上面答案建立此表格

表格1-1

%rax System call %rdi %rsi %rdx %r10 %r8 %r9
1 __x64_sys_write fd buf count

參考資源:

C/C++ function definitions without assembly

How can I find the implementations of Linux kernel system calls?

linux system call

輸出範例

C內嵌ASM

實做直接呼叫linux system code

根據1-1表格找到的資訊

關於此段指令為什麼填入1的理由

"mov $1, %%rdi\n"

Print

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
void print_asm(char *arg1,long int size){ 
    __asm__ (
        "mov $1, %%rax\n"//system call 編碼
        "mov $1, %%rdi\n"//fd 設定1 代表把字串輸入/dev/stdout 這裡就是螢幕輸出地方
        "mov %0,%%rsi\n"//輸入字串記憶體位置
        "mov %1, %%rdx\n" //這裡輸入字串長度 ,可以跟記憶體位置搭配來輸出到螢幕
        "syscall"//x64 要用此呼叫systemcall 不能在使用int $0x80
        :
        :"m" (arg1),"m" (size) //詳細請參考gcc inline asm
    );
}
int main(void) {
    char *d="ss\n";
    print_asm(d,3);
return 0;
}

C & ASM混和編譯

ss

評論